package cn.skcks.shirospringboot.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
	// 创建 realm 对象, 需 自定义类
	@Bean(name = "userRealm")
	public UserRealm userRealm(){
		return new UserRealm();
	}

	// DefaultWebSecurityManager
	@Bean(name = "securityManager")
	public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

		// 关联 UserRealm
		securityManager.setRealm(userRealm);

		return securityManager;
	}

	// ShiroFilterFactoryBean
	@Bean
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

		// 设置安全管理器
		shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

		// 设置登录页
		shiroFilterFactoryBean.setLoginUrl("/login");

		// 设置未授权访问错误页面
		shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

		// 添加 shiro 的内置过滤器
		// anon 无需认证即可范围
		// authc 必须认证才能访问
		// perms 拥有某个资源的权限才能访问
		// role 拥有某个角色权限才能访问
		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
		filterChainDefinitionMap.put("/","anon");
		filterChainDefinitionMap.put("/index","anon");

		filterChainDefinitionMap.put("/user/list","authc");

		filterChainDefinitionMap.put("/user/add","perms[user:add]");
		// 支持通配符
		filterChainDefinitionMap.put("/user/*","authc");

		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);


		return shiroFilterFactoryBean;
	}

	// 整合 ShiroDialect
	@Bean
	public ShiroDialect getShiroDialect(){
		return new ShiroDialect();
	}
}